package com.jctrip.hotel.management.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jctrip.hotel.common.enums.OrderStatusEnum;
import com.jctrip.hotel.common.enums.RouteTypeEnum;
import com.jctrip.hotel.common.route2source.model.param.Route2SourceCancelOrderParam;
import com.jctrip.hotel.common.route2source.service.Route2SourceOrderService;
import com.jctrip.hotel.domain.dao.*;
import com.jctrip.hotel.domain.entity.*;
import com.jctrip.hotel.management.model.param.CancelOrderParam;
import com.jctrip.hotel.management.util.JwtUtil;
import com.jctrip.hotel.route.common.ThreadLocalSession;
import com.jctrip.hotel.route.model.result.CancelOrderResult;
import com.jctrip.hotel.route.service.RouteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 取消订单接口-服务
 */
@Service
@Slf4j
public class CancelOrderManageService extends RouteService {

    @Autowired
    private HtOrderRouteRecordDao htOrderRouteRecordDao;

    @Autowired
    private HtOrderSourceRecordDao htOrderSourceRecordDao;

    @Autowired
    private Route2SourceOrderService route2SourceOrderService;

    @Autowired
    private HtRouteInfoDao htRouteInfoDao;

    @Autowired
    private HtRouteCreditLogDao htRouteCreditLogDao;

    @Autowired
    private MgOrderLogDao mgOrderLogDao;

    public CancelOrderResult execute(CancelOrderParam param, HttpServletRequest req) {
        HtRouteInfo htRouteInfo = htRouteInfoDao.selectOne(new LambdaQueryWrapper<HtRouteInfo>()
                .eq(HtRouteInfo::getRouteId,param.getRouteId()));
        String routeId = htRouteInfo.getRouteId();
        HtOrderRouteRecord htOrderRouteRecord = param.getRouteOrderId() == null
                ? getOrderRouteRecord(param.getOrderId())
                : getOrderRouteRecord(routeId, param.getRouteOrderId());
        if (htOrderRouteRecord == null) {
            throw new RuntimeException("orderId或者routeOrderId无效");
        }
        if (!htOrderRouteRecord.getRouteId().equals(routeId)) {
            throw new RuntimeException("没有权限的订单");
        }
        HtOrderSourceRecord htOrderSourceRecord = getOrderManagementSourceRecord(htOrderRouteRecord.getOrderId(), param.getBookId());
        if (htOrderSourceRecord == null) {
            throw new RuntimeException("没有供应下单记录");
        }
        // 防止远端处于下单成功而我们处于下单失败场景
//        if (htOrderSourceRecord.getSourceOrderStatus() != 1){
//            throw new RuntimeException("该订单未处于预定成功状态");
//        }
        HtSourceInfo htSourceInfo = getSourceInfo(htOrderSourceRecord.getSourceId());
        // 取消订单
        Route2SourceCancelOrderParam cancelOrderParam = Route2SourceCancelOrderParam.builder()
                .sourceCode(htOrderSourceRecord.getSourceCode())
                .sourceAppId(htSourceInfo.getSourceAppId())
                .sourceSecret(htSourceInfo.getSourceSecret())
                .bookId(htOrderSourceRecord.getBookId())
                .sourceOrderId(htOrderSourceRecord.getSourceOrderId())
                .hotelId(htOrderSourceRecord.getHotelId())
                .extra(htSourceInfo.getExtra())
                .build();
        route2SourceOrderService.cancelOrder(cancelOrderParam);
        htRouteInfo = htRouteInfoDao.selectById(htRouteInfo.getId());
        /* 更新渠道账户信息 */
        updateRouteInfo(htRouteInfo, htOrderRouteRecord);
        /* 保存账户额度记录 */
        insertRouteCreditLog(htRouteInfo, htOrderRouteRecord);
        try{
            /* 保存订单日志 */
            insertOrderLog(htRouteInfo, htOrderRouteRecord, req);
        } catch (Exception e){
            log.info(e.getMessage());
        }
        // 更新渠道订单
        updateOrderRouteRecord(htOrderRouteRecord);
        // 更新供应订单
        updateOrderSourceRecord(htOrderSourceRecord);
        return CancelOrderResult.builder().build();
    }

    private void insertOrderLog(HtRouteInfo htRouteInfo, HtOrderRouteRecord htOrderRouteRecord, HttpServletRequest request){
        MgOrderLog mgOrderLog = new MgOrderLog();
        mgOrderLog.setRouteId(htRouteInfo.getRouteId());
        mgOrderLog.setOrderId(htOrderRouteRecord.getOrderId());
        mgOrderLog.setInfo(String.format("%s订单取消",htOrderRouteRecord.getOrderId()));
        mgOrderLog.setOperator(StringUtils.isNotBlank(request.getHeader("token")) ?
                JwtUtil.parseJwt(request.getHeader("token")).getSubject() : "system");
        mgOrderLogDao.insert(mgOrderLog);
    }

    private void updateRouteInfo(HtRouteInfo htRouteInfo, HtOrderRouteRecord htOrderRouteRecord) {
        if (htRouteInfo.getRouteType() != RouteTypeEnum.OUTER.getCode()) {
            return;
        }
        BigDecimal newCredit = htRouteInfo.getAccountCredit().add(htOrderRouteRecord.getPaymentPrice());
        htRouteInfo.setAccountCredit(newCredit);
        htRouteInfoDao.updateById(htRouteInfo);
    }

    private void insertRouteCreditLog(HtRouteInfo htRouteInfo, HtOrderRouteRecord htOrderRouteRecord) {
        if (htRouteInfo.getRouteType() != RouteTypeEnum.OUTER.getCode()) {
            return;
        }
        HtRouteCreditLog htRouteCreditLog = new HtRouteCreditLog();
        htRouteCreditLog.setRouteId(htRouteInfo.getRouteId());
        htRouteCreditLog.setOrderId(htOrderRouteRecord.getOrderId());
        htRouteCreditLog.setCreditType(2);
        htRouteCreditLog.setAmountOfChange(htOrderRouteRecord.getPaymentPrice());
        htRouteCreditLog.setAccountCredit(htRouteInfo.getAccountCredit());
        htRouteCreditLog.setOperator("system");
        htRouteCreditLogDao.insert(htRouteCreditLog);
    }

    private void updateOrderRouteRecord(HtOrderRouteRecord htOrderRouteRecord) {
        htOrderRouteRecord.setRouteOrderStatus(50);
        htOrderRouteRecord.setOrderRefundTime(new Date());
        htOrderRouteRecord.setOrderCancelTime(new Date());
        htOrderRouteRecordDao.updateById(htOrderRouteRecord);
    }

    private void updateOrderSourceRecord(HtOrderSourceRecord htOrderSourceRecord) {
        htOrderSourceRecord.setSourceOrderStatus(OrderStatusEnum.CANCELED.getCode());
        htOrderSourceRecord.setOrderModifyTime(new Date());
        htOrderSourceRecordDao.updateById(htOrderSourceRecord);
    }

    private HtOrderSourceRecord getOrderManagementSourceRecord(String orderId, String bookId) {
        LambdaQueryWrapper<HtOrderSourceRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HtOrderSourceRecord::getOrderId, orderId);
        queryWrapper.eq(StringUtils.isNotBlank(bookId), HtOrderSourceRecord::getBookId, bookId);
        List<HtOrderSourceRecord> htOrderSourceRecords = htOrderSourceRecordDao.selectList(queryWrapper);
        return htOrderSourceRecords.stream()
                .max(Comparator.comparing(HtOrderSourceRecord::getCreateTime))
                .orElse(null);
    }
}
